unit mdef;

interface

	{ A code resource must have no global variables.  All shared variables are }
	{ local procedure MAIN, and shared among its sub procedures }

	procedure Our_Custom_Menu (message: integer;
									theMenu: MenuHandle;
									var menuRect: Rect;
									hitPt: Point;
									var whichItem: integer);	{ a code resource must have a procedure called MAIN }

implementation

{********************************************************************** }
{                                                                       }
{  entry point for our <M>enu <DEF>inition                              }
{                                                                       }
{  This menu displays patterns taken from the System PAT#.              }
{  The size of the rectangles for each pattern are designated           }
{  by PRECTWIDE and PRECTHIGH.  The menu is drawn with the              }
{  rectangles, PATROWS high and PATCOLS wide, in this case,             }
{  8 patterns high by 5 patterns wide.                                  }
{  The MenuItem returned by the MDEF is the index within the            }
{  PAT# of the pattern chosen by the user, and can be found with...     }
{                                                                       }
{     GetIndPattern(&somePatternVariable,LISTID,MenuItem);              }
{                                                                       }
{  From the LightspeedC "Project" menu:                                 }
{                                                                       }
{     "Set Project Type..."                                             }
{     ---------------------------------------                           }
{               Code Resource                                           }
{     Type      MDEF                                                    }
{     Id        130                                                     }
{     Name      Pattern Menu [optional]                                 }
{                                                                       }
{     "Build Code Resource..."                                          }
{     "MDEF Code" if you're using the "XFER MDEF" project to            }
{     copy the MDEF and place it in the "patmenudemo.rsrc" file         }
{********************************************************************** }

	procedure Our_Custom_Menu;

		const
			PRECTWIDE = 32;		{ how wide are the patterns	}
			PRECTHIGH = 32;		{ how high are the patterns }
			PATROWS = 8;		    { number of rows in menu }
			PATCOLS = 5;		    { number of columns in menu	}
			LISTID = 1000;    { Resource ID of PAT# }

		procedure calcitemrect (MenuRect: Rect;
										var resultRect: Rect;
										item: integer);

			var
				row, col: integer;

{ calculate the rectangle within the menu, (therefore, within MenuRect), }
{ for any given menu item designated by "item".  Find out which row and }
{ column the item is in, then construct the rectangle, and return the }
{ rectangle as the function result }

		begin
			row := (item - 1) div PATCOLS;
			col := (item - 1) mod PATCOLS;
			resultRect.left := MenuRect.left + col * PRECTWIDE;
			resultRect.top := MenuRect.top + row * PRECTHIGH;
			resultRect.right := resultRect.left + PRECTWIDE;
			resultRect.bottom := resultRect.top + PRECTHIGH;
		end;

		procedure domenudraw (menuRect: Rect);

			var
				itemRect: Rect;
				thePat: Pattern;
				index: integer;

{ cycle through PATROWS * PATCOLS items, getting a pattern from the }
{ System PAT#, and filling the menu rectangles with that pattern }

		begin
			for index := 1 to (PATROWS * PATCOLS) do
				begin
					GetIndPattern(thePat, LISTID, index);	{ get the pattern }
					calcitemrect(menuRect, itemRect, index);	{ calculate the rectangle in the menu }
					InsetRect(itemRect, 1, 1);	{ draw the menu item }
					FillRect(itemRect, thePat);
					FrameRect(itemRect);
				end;
		end;

		procedure domenuchoose (menuRect: Rect;
										hitPt: Point;
										var whichItem: integer);

			var
				index, itemChosen: integer;
				testRect, oldRect: Rect;

		begin
			itemChosen := 1000;
{ an impossible menu choice }
{ find out which menu item rectangle the mouse is in }
			for index := 1 to PATROWS * PATCOLS do
				begin
					calcitemrect(menuRect, testRect, index);
					if PtInRect(hitPt, testRect) then
						begin
{ the mouse is in the "indexth" menu item }
							itemChosen := index;
		{	break; }
						end;
				end;
			if itemChosen <> 1000 then
				begin
{ then we found the mouse in a menu item. was there an old menu item selected? }
					if ((whichItem <> 0) and (whichItem <> itemChosen)) then
						begin
{ if so, then un-select it }
							calcitemrect(menuRect, oldRect, whichItem);
							PenMode(patXor);
							FrameRect(oldRect);
						end;
{ tell the menu manager which item was last selected and select it }
					whichItem := itemChosen;
					calcitemrect(menuRect, oldRect, itemChosen);
					PenMode(patCopy);
					FrameRect(oldRect);
				end
			else if not PtInRect(hitPt, menuRect) then
{ no menu item was selected, so un-select any previous menu item selected }
				begin
					calcitemrect(menuRect, oldRect, whichItem);
					PenMode(patXor);
					FrameRect(oldRect);
					whichItem := 0;
				end;
		end;

		procedure domenusize (var theMenu: Menuhandle);

		begin
{ tell the menu manager how large the menu rectangle is }
			theMenu^^.menuWidth := PATCOLS * PRECTWIDE;
			theMenu^^.menuHeight := PATROWS * PRECTHIGH;
		end;

	begin
	{ what does the menu manager want us to do? }
		case message of
			mDrawMsg: 
				domenudraw(menuRect);

			mChooseMsg: 
				domenuchoose(menuRect, hitPt, whichItem);

			mSizeMsg: 
				domenusize(theMenu);

			otherwise
				;
		end;
	end;

end.